package com.fdb.efp.esb.service.impl.yx;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fdb.efp.esb.common.constant.ESBTradeNoConstance;
import com.fdb.basic.framework.core.constant.ESBConstant;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.SpringContextUtils;
import com.fdb.efp.esb.service.bo.req.hlw.ReqAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.req.yx.YedApplyRiskApproveReq;
import com.fdb.efp.esb.service.bo.resp.hlw.RespAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.resp.yx.YedApplyRiskApproveResp;
import com.fdb.efp.esb.service.client.ESBBeanCreator;
import com.fdb.efp.esb.service.client.impl.BDESBBeanCreator;
import com.fdb.efp.esb.service.facade.hlw.AlarmJudgementService;
import com.fdb.efp.esb.service.impl.esb.AbstractRetryBaseEsbService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

/**
 * 优e贷用信阶段风控审批接口调用
 *
 * @author liangcongming :2020/7/31 10:50
 * @version 0.1
 * @date 2020/7/31 10:50
 * @since 2020/7/31 10:50
 */
@Service("yedApplyRiskApproveService")
public class YedApplyRiskApproveServiceImpl extends AbstractRetryBaseEsbService<YedApplyRiskApproveReq, YedApplyRiskApproveResp> {

    private static Logger logger = LoggerFactory.getLogger(YedApplyRiskApproveServiceImpl.class);

    @Autowired
    @Qualifier("alarmJudgementService")
    private AlarmJudgementService alarmJudgementService;


    @Override
    protected String applySeq(YedApplyRiskApproveReq reqBean) {
        if (reqBean.getApplyInfArry().size() > 0) {
            return reqBean.getApplyInfArry().get(0).getAppNo();
        } else {
            return "";
        }
    }

    @Override
    protected YedApplyRiskApproveResp postProcess(YedApplyRiskApproveReq reqBean, YedApplyRiskApproveResp resBean) throws Exception {
        Optional.
                ofNullable(resBean).
                map(i -> i.getApplyRiskInfArry().get(0).getRcvSt()).
                orElseThrow(() -> new ESBException("优e贷授信风控审批接口返回为空！"));
        logger.debug("优e贷用信风控审批接口进行后续处理，请求参数: " + reqBean + ", 返回结果： " + resBean);
        return resBean;
    }

    @Override
    protected String tradeNo() {
        return ESBTradeNoConstance.YED_CREDIT_RISK;
    }

    @Override
    protected String scene() {
        return ESBConstant.SCENE_NO_12;
    }

    @Override
    protected Function<String, YedApplyRiskApproveResp> converter() {
        return i -> JSONObject.parseObject(i, new TypeReference<YedApplyRiskApproveResp>() {
        });
    }

    @Override
    protected ESBBeanCreator beanFactory() {
        return (BDESBBeanCreator) SpringContextUtils.getBean("BDESBBeanCreator");
    }

    /**
     * 执行次数，包括第一次执行
     * 若为3，则第一次执行出错后还会执行2次重试
     *
     * @return
     */
    @Override
    protected Integer retryTimes() {
        return 4;
    }

    /**
     * 等待时间 2分钟
     *
     * @return 单位：毫秒
     */
    @Override
    protected Long waitTime() {
        return 2 * 60 * 1000L;
    }

    /**
     * 等待时间跨度
     * 默认为1，若等待时间为5s，跨度为1，则每次间隔的等待时间为5*1=5s, 5*1=5s, 10*1=5s
     * 若等待时间为5s，跨度为2，则每次间隔的等待时间为5*1=5s, 5*2=10s, 10*2=20s
     * 若等待时间为5s，跨度为3，则每次间隔的等待时间为5*1=5s, 5*3=15s, 10*3=30s
     *
     * @return
     */
    @Override
    protected Long timeSpan() {
        return 1L;
    }

    /**
     * 重试失败后执行的操作
     */
    @Override
    protected void retryFailCallback(YedApplyRiskApproveReq reqBean) throws Exception {
        //调用风控失败3次之后，发告警信息
        ReqAlarmJudgementBean reqAlarmJudgementBean = new ReqAlarmJudgementBean();
        reqAlarmJudgementBean.setAlrmInf("优e贷用信阶段风控审批接口调用3次失败！流水号：" + reqBean.getApplyInfArry().get(0).getAppNo());
        getrespAlarmJudgementBean(reqAlarmJudgementBean);
        logger.error("优e贷用信阶段风控审批接口调用重试失败！流水号：" + reqBean.getApplyInfArry().get(0).getAppNo());
        throw new ESBException("优e贷用信阶段风控审批接口调用3次失败");
    }

    /**
     * 允许自定义成功和失败的判断标准
     * @param res 调用返回值
     * @return
     */
    @Override
    protected boolean isSuccess(YedApplyRiskApproveResp res) {
        Map<String,String> map = initMap();
        if(map.keySet().contains(res.getApplyRiskInfArry().get(0).getRcvSt())){
            return true;
        }
        return false;
    }

    /**
     * 优e贷用信审批风控返回码值
     * @return
     */
    private Map<String,String> initMap(){
        Map<String,String> map = new HashMap<String,String>();
        map.put("4001000EX000001","申请流水号重复");
        map.put("4001000EX000002","业务流水号为空");
        map.put("4001000EX000003","请求报文异常");
        map.put("4001000EX000004","响应异常");
        map.put("4001000EX000005","调用外部数据源异常");
        map.put("4001000EX000006","系统未知异常");
        map.put("4001000EX000007","服务码场景码异常或未配置");
        map.put("4001000EX000008","请求信息为空");
        map.put("4001000EX000009","服务码或场景码为空");
        map.put("4001000EX000010","程序错误异常");
        map.put("000000","接收处理成功");
        return map;
    }

    /**
     *
     * 调用颖风写的告警判断服务
     *
     * @param reqAlarmJudgementBean
     * @return
     * @throws Exception
     * @author liyakui
     * @since 2019年1月28日 上午8:36:25
     * @version 1.0
     */
    public RespAlarmJudgementBean getrespAlarmJudgementBean(ReqAlarmJudgementBean reqAlarmJudgementBean) throws Exception {
        RespAlarmJudgementBean respAlarmJudgementBean = null;
        try {
            // 调用颖风写的告警判断服务
            reqAlarmJudgementBean.setMonObjNm("优e贷");
            reqAlarmJudgementBean.setMonObjSpfTpVal("外部接口");
            reqAlarmJudgementBean.setMonObjLctr(InetAddress.getLocalHost().getHostAddress());// 获取本机IP
            reqAlarmJudgementBean.setAlrmTmstmp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((new Date())));
            reqAlarmJudgementBean.setMonAlrmLvl("3");
            respAlarmJudgementBean = alarmJudgementService.alarmJudgement(reqAlarmJudgementBean);
            logger.debug("调用告警判断返回码：【" + respAlarmJudgementBean.getRetCd() + "】，返回信息：【" + respAlarmJudgementBean.getRetMsg() + "】");
        } catch (Exception e) {
            logger.info("调用告警接口异常！" + e.getMessage());
            throw e;
        }
        return respAlarmJudgementBean;
    }
}
